<?php

namespace app\common\model;

use fast\Http;
use IEXBase\TronAPI\Tron;
use think\Model;
use think\Db;

/**
 * 波场币模型
 */
class Trx extends Model
{
    protected static $contract_address = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';
    public static $decimals = 6;//通证精度

    protected static function init()
    {
    }

    public function __construct($data = [])
    {
        parent::__construct($data);
    }

    /**
     * 验证地址是否有效
    */
    public static function validateAddress($address)
    {
        $tron = new Tron();
        return $tron->validateAddress($address);
    }

    /**
     * 创建地址
    */
    public static function create_address($uid)
    {
        $tron = new Tron();
        $generateAddress = $tron->generateAddress();
        $address_info = $generateAddress->getRawData();
        if (isset($address_info['address_base58']) && !empty($address_info['address_base58'])) {
            if ($uid > 0) {
                $wallet = Db::name('wallet')->where(['uid' => $uid, 'coin_id' => config('usdt_id')])->find();
                $exist = Db::name('wallet_address')->where(['wallet_id' => $wallet['id']])->find();
                $data = [
                    'wallet_id' => $wallet['id'],
                    'coin_id' => $wallet['coin_id'],
                    'uid' => $uid,
                    'address' => $address_info['address_base58'],
                    'public_key' => $address_info['public_key'],
                    'private_key' => $address_info['private_key']
                ];
                if (!$exist) {
                    Db::name('wallet_address')->insert($data);
                } else {
                    Db::name('wallet_address')->where(['wallet_id' => $wallet['id']])->update($data);
                }

                return ['error' => 0, 'msg' => '生成地址成功', 'data' => $address_info['address_base58']];
            } else {
                return $address_info;
            }
        } else {
            return ['error' => 1, 'msg' => '生成地址失败'];
        }
    }

    /**
     * 获取充值记录
    */
    public static function get_recharge($uid)
    {
        $usdt_id = config('usdt_id');
        $address = Db::name('wallet_address')->where(['uid' => $uid, 'coin_id' => $usdt_id])->value('address');
        $url = "https://api.trongrid.io/v1/accounts/".$address."/transactions/trc20?limit=20&order_by=timestamp,desc&only_confirmed=true&only_to=true&contract_address=". self::$contract_address;
        $data = Http::get($url);
        $data = json_decode($data, true);
        if (isset($data['success']) && $data['success'] == true) {
            foreach ($data['data'] as $datum) {
                $exist = Db::name('bill_order')->where(['uid' => $uid, 'coin_id' => $usdt_id, 'type' => LogType::get_type_id('recharge_coin'), 'tradeid' => $datum['transaction_id']])->find();
                $number = bcdiv($datum['value'], pow(10, self::$decimals), 6);
                if (!$exist) {
                    $bill_id = BillOrder::add_bill($uid, '',  $datum['transaction_id'], 1, $number, $usdt_id, 0, 'recharge_coin');
                    if ($bill_id > 0) {
                        Wallet::up_coin($uid, $number, $usdt_id, 'recharge_coin', $bill_id);
                    }
                }
            }
        } else {
            return ['error' => 1, 'msg' => '获取充值记录失败'];
        }

        return ['error' => 0];
    }

    /**
     * 获取手续费地址等信息
    */
    public static function get_fee_info()
    {
        $fee_address = Config::get_config('trx20_fee_address');
        $fee_key = Config::get_config('trx20_fee_key');
        if (empty($fee_key)) {
            $fee_info = self::create_address(-10);
            $fee_address = $fee_info['address_base58'];
            $fee_key = $fee_info['private_key'];
            Db::name('config')->where(['name' => 'trx20_fee_address'])->update(['value' => $fee_address]);
            Db::name('config')->where(['name' => 'trx20_fee_key'])->update(['value' => $fee_key]);
        }
        return ['fee_address' => $fee_address, 'fee_key' => $fee_key];
    }

    /**
     * 审核提现转账
    */
    public static function confirm_withdraw($order_id)
    {
        $fee_info = self::get_fee_info();
        $fee_balance = self::get_balance($fee_info['fee_address']);
        if ($fee_balance <= 0) {
            return ['error' => 1, 'msg' => '手续费地址余额为0，无法提现'];
        } else {
            $order_info = model("BillOrder")->get($order_id);
            if ($order_info['status'] == 1) {
                return ['error' => 1, 'msg' => '该订单已经审核通过'];
            } elseif ($fee_balance < $order_info['amount']) {
                return ['error' => 1, 'msg' => '手续费地址余额小于订单金额，无法提现'];
            } elseif (empty($order_info['to_address'])) {
                return ['error' => 1, 'msg' => '提现地址不能为空'];
            } else {
                $validateAddress = self::validateAddress($order_info['to_address']);
                if ($validateAddress['result'] != true) {
                    return ['error' => 1, 'msg' => '提现地址不是有效的TRX20地址'];
                }
                $result = self::trx20_transfer($fee_info['fee_address'], $fee_info['fee_key'], $order_info['to_address'], $order_info['amount']);
                if ($result['error'] > 0) {
                    return $result;
                } else {
                    model('BillOrder')->where(['id' => $order_id])->update(['status' => 1]);
                    return ['error' => 0];
                }
            }
        }
    }

    /**
     * 获取地址的余额
    */
    public static function get_balance($address)
    {
        $tron = new Tron();
        $abi = json_decode(config('abi.abi'), true);
        $a = $tron->getTransactionBuilder()->triggerConstantContract($abi, $tron->toHex(self::$contract_address), 'balanceOf', ['0' => $tron->toHex($address)], $tron->toHex($address));

        $u_b = json_decode($a[0], true);//usdt余额
        $u_balance = bcdiv($u_b, pow(10, self::$decimals), 8);

        return $u_balance;
    }

    /**
     * 转账接口
     * @param string $from_address 转出地址
     * @param string $from_private_key 转出地址的密钥
     * @param string $to_address 转入地址
     * @param float $num 转入数量
    */
    public static function trx20_transfer($from_address, $from_private_key, string $to_address, float $num)
    {
        $tron = new Tron();
        $tron->setPrivateKey($from_private_key);
        $num = bcmul($num, 1000000);
        $abi = json_decode(config('abi.abi'), true);
        $b = $tron->getTransactionBuilder()->triggerSmartContract($abi, $tron->toHex(self::$contract_address), 'transfer', ['0' => $tron->toHex($to_address), '1' => $num], pow(10, self::$decimals), $tron->toHex($from_address));
        //签名
        $c = $tron->signTransaction($b);
        //广播
        $d = $tron->sendRawTransaction($c);
        if (isset($d['result']) && isset($d['txid'])) {
            return ['error' => 0, 'msg' => '转账成功', 'data' => $d];
        } else {
            $message = pack("H*", $d['message']);
            return ['error' => 1, 'msg' => '转账失败；' . $message];
        }
    }

    /**
     * 查询转账是否成功
    */
    public static function getEventByTransactionID($transactionId = '60f42edba67ec34563732323fc508a291e1baf23b376eed83e918c5bd70f8d81')
    {
        $tron = new Tron();
        $result = $tron->getEventByTransactionID($transactionId);
        $num = 0;
        if (isset($result[0]['result']['value'])) {
            $num = $tron->fromTron($result[0]['result']['value']);
        }
        return $num;
    }
}
